/**
 * Copyright (c) 2010
 * Bert Young. UESTC. 
 */

#ifndef BERT_TCPTASK_H
#define BERT_TCPTASK_H
#include "debug.h"

#include "SocketConnection.h"
#include "Timer.h"
#include "Entry.h"
#include "MsgBuffer.h"

#if 0
#include "TaskManager.h"
class TCPTaskBuffer;
extern TaskManager<TCPTaskBuffer> globalManager;
#endif
class TCPTask : public Entry
{
protected:
	/**
	 * The real connection
	 */
	SocketConnection socket;
private:
	/**
	 * Buffered or nonbuffer
	 */
	bool buffered;
	static int uniqueid;// for test, consider for unique id creator
public:
	/**
	 * State of this connection
	 */
	enum ConnectionState
	{
		idle,
		verify,
		okay,
		recycle,
	} state;
	/**
	 * Disconnect type
	 */
	enum DisconnectType
	{
		disconnect_none,
		disconnect_active,
		disconnect_passive,
	} disconnect;
private:
	/**
	 * Is the remote client pass through
	 */
	//bool verified;
	/**
	 * When this connection is created
	 */
	Time bornTime;
	/**
	 * The timer of heartbeat tick
	 */
	Timer heartbeatTimer;
	/**
	 * Our heartbeat tick has sent or not
	 */
	bool beatSent;
public:
	/**
	 * Constructor
	 */
	TCPTask(int localfd = -1, const struct sockaddr_in * client=NULL, bool buffer = false);
	/**
	 * Destructor
	 */
	virtual ~TCPTask()
	{
#ifdef CHINESE
		debug("关闭连接id = %d", this->id );
#else
		debug("close task id = %d", this->id );
#endif
		//socket.finalSync();
	}
	/**
	 * 验证是否超时
	 */
	bool checkVerifyTimeout(const Time & now, unsigned long out = 5000L) const
	{
		return now.msec() - bornTime.msec() > out;
	}
	/**
	 * 先收到客户传来的验证消息；通过后，将自己进入okay状态
	 * 回一个消息给客户，然后调用addcontainer把自己放入到taskManager中
	 */
	virtual int verifyConn()
	{	// recvtobuf_nopoll; recvtocmd_nopoll
		// error -1 ;    0 timeout
		return 1;
	}
	/**
	 * 不知有什么用
	 */
	virtual int recycleConn()
	{
		return 1;
	}
	/**
	 * Check heartbeat, return whether the remote is alive
	 */
	bool checkHeartbeat(const Time & now);
	/**
	 * set state
	 */
	void nextState();
	/**
	 * reset state
	 */
	void resetState()
	{
		this->state = recycle;
		this->buffered = false;
	}
	/**
	 * Send cmd
	 */
	bool sendPacket(const void * cmd, unsigned int len);
	/**
	 * Receive data
	 */
	bool recv(bool needRecv = true);
	/**
	 * Send data
	 */
	bool send();
	/**
	 * Parse the cmd or put it into buffer for logical thread to parse it
	 */
	virtual void parse(const void * cmd, unsigned int len) //= 0;//for test
	{
	}
	/**
	 * For epoll me
	 */
	void epollAdd(int epfd, __uint32_t events, void * ptr )
	{
		this->socket.epollAdd(epfd, events, ptr);
	}
	/**
	 * 从epoll中移除
	 */
	void epollDel( int epfd )
	{
		this->socket.epollDel(epfd);
	}
	/**
	 * 连接的唯一id
	 */
	unsigned int getID() const
	{
		return Entry::id;
	}
	/**
	 * 设置断开标志
	 */
	void setDisconnect(DisconnectType type)
	{
		this->disconnect = type;
	}
	/**
	 * 该断开吗
	 */
	bool shouldDisconnect()
	{
		return this->disconnect != disconnect_none;
	}
	/**
	 * 发数据包是否缓冲
	 */
	bool setBuffer(bool buffer = true)
	{
		return this->buffered = buffer;
	}
	/**
	 * 在验证线程通过了verifyConn之后，再添加到SUPERTASKMANAGER
	 */
	virtual bool addToContainer()
	{//如果add失败，那就设置disconnect
		return true;
	}
	/**
	 * 在回收线程通过了recycleConn之后，再移出SUPERTASKMANAGER
	 */
	virtual bool removeFromContainer()
	{
		return true;
	}
	/*
	bool unique;
	void setUnique()
	{
		unique = true;
	}*/
	/**
	 * 我发消息cmd，远端的clienttask正在checkrebound函数里等待cmd
	 */
	virtual int waitSync()
	{
		return 1;
	}
	/**
	 * Is epolled for read
	 */
	bool isEpollRead;
	/**
	 * 本连接的远端客户类型,也就是我为谁服务
	 */
	bool taskType;
	/**
	 * 为断线重连设置，网关服务器应该让它返回false
	 */
	virtual bool TerminateError()
	{
		return true;
	}
};

class TCPTaskNoBuffer : public TCPTask, public MsgParse 
{
public:
	/**
	 * Constructor
	 */
	TCPTaskNoBuffer(int localfd=-1, const struct sockaddr_in * client=NULL, bool buffer=false):TCPTask(localfd, client, buffer)
	{
	}
	/**
	 * 在OKAY线程直接解析消息；也就是IO与逻辑耦合
	 */
	virtual void parse(const void * cmd, unsigned int len);
};

class TCPTaskBuffer : public TCPTask, public MsgBuffer
{
public:
	/**
	 * Constructor
	 */
	TCPTaskBuffer(int localfd=-1, const struct sockaddr_in * client=NULL, bool buffer=false):TCPTask(localfd, client, buffer)
	{
	}
	/**
	 * 在逻辑线程解析消息；也就是IO与逻辑分离
	 */
	virtual void parse(const void * cmd, unsigned int len);
};

#endif

